package com.aiyige.utils.ffmpeg;

import android.app.Activity;
import android.media.MediaMetadataRetriever;
import android.os.Environment;
import android.os.PowerManager;
import android.text.TextUtils;
import android.util.Log;

import com.aiyige.MyApp;
import com.aiyige.utils.TimeUtils;
import com.aiyige.utils.ToastX;
import com.vondear.rxtools.RxFileTool;
import com.yyl.ffmpeg.FFmpegCallBack;
import com.yyl.ffmpeg.FFmpegUtils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;

import timber.log.Timber;

import static com.aiyige.configs.MyConfig.AIYIGE_ROOT_DIR;

/**
 * Created by xiachao on 2017/11/3.
 */

public class TranscoderUtils {

    private static String TAG = "TranscoderUtils";

    private static final String TRANSCODER_DIR = AIYIGE_ROOT_DIR + "transcoder" + File.separator;

    private static final String VIDEO_DIR = TRANSCODER_DIR + "video" + File.separator;

    private static final String NO_MEDIA = AIYIGE_ROOT_DIR + ".nomdia";

    private static final String WATERMARK_DIR = TRANSCODER_DIR + "watermark" + File.separator;

    private static final String WATERMARK_PATH = WATERMARK_DIR + "logo.png";

    FFmpegUtils ffmpeg;
    PowerManager.WakeLock wakeLock;

    long mDuration;

    public void setCallback(TranscoderCallback callback) {
        this.callback = callback;
    }

    String videoInputPath;
    String videoOutputPath;

    TranscoderCallback callback;

    VideoEntity videoEntity;

    private String[] createCommand(String path) {
        if (TextUtils.isEmpty(path)) {
            return null;
        }
        File file = new File(path);
        if (!file.exists()) {
            return null;
        }
        videoEntity = new VideoEntity();
        MediaMetadataRetriever mmr = new MediaMetadataRetriever();
        try {
            mmr.setDataSource(path);
            String title = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE); // api level 10, 即从GB2.3.3开始有此功能
            videoEntity.setTitle(title);
            String duration = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION); // 播放时长单位为毫秒
            videoEntity.setDuration(TextUtils.isEmpty(duration) ? 0 : Long.parseLong(duration));
            String bitrate = "";
            if (TextUtils.isEmpty(duration) || duration.equals("0")) {
                this.mDuration = (int) videoEntity.getDuration();
                if (this.mDuration == 0) {
                    String cmd = "ffprobe -v quiet -print_format json -show_format -i " + path;
                    String json = ffmpeg.execffprobe(cmd);
                    VideoBeanJson beanJson = VideoBeanJson.getJson(json);
                    if (beanJson != null) {
                        this.mDuration = beanJson.getTime();
                        videoEntity.setDuration(this.mDuration);
                        VideoBeanJson.FormatBean formatBean = beanJson.getFormat();
                        if (formatBean != null) {
                            bitrate = TextUtils.isEmpty(formatBean.getBit_rate()) ? 0 + "" : Long.parseLong(formatBean.getBit_rate()) + "";
                            videoEntity.setBitrate(TextUtils.isEmpty(formatBean.getBit_rate()) ? 0 : Long.parseLong(formatBean.getBit_rate()));
                        }
                    }
                }
            } else {
                bitrate = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_BITRATE); // 从api level 14才有，即从ICS4.0才有此功能
                videoEntity.setBitrate(TextUtils.isEmpty(bitrate) ? 0 : Integer.parseInt(bitrate));
            }
            String width = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH);// 视频宽
            videoEntity.setWidth(TextUtils.isEmpty(width) ? 0 : Integer.parseInt(width));
            String height = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT);// 视频高
            videoEntity.setHeight(TextUtils.isEmpty(height) ? 0 : Integer.parseInt(height));
            String framerate = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_CAPTURE_FRAMERATE);//帧率
            videoEntity.setFramerate(TextUtils.isEmpty(framerate) ? 0 : Integer.parseInt(framerate));
            if (callback != null) {
                String avinfo = "原视频名称：" + file.getName()
                        + "\n分辨率:" + width + "x" + height
                        + "\n码率:" + videoEntity.getBitrateValue()
                        + "\n时长:" + TimeUtils.stringForTime(this.mDuration)
                        + "\n大小:" + ((((double) file.length()) / 1024) / 1024) + "MB";
                callback.start(avinfo);
            }


        } catch (IllegalArgumentException e) {
            e.printStackTrace();
            if (callback != null) {
                callback.failed("抱歉，视频无法转换" + e.toString());
            }
            return null;
        } catch (IllegalStateException e) {
            e.printStackTrace();
            if (callback != null) {
                callback.failed("抱歉，视频无法转换" + e.toString());
            }
            return null;
        }

        videoOutputPath = VIDEO_DIR + getFileName(path);


//        0 = "ffmpeg"
//        1 = "-ss"
//        2 = "00:00:10"
//        3 = "-t"
//        4 = "00:01:01"
//        5 = "-i"
//        6 = "/storage/emulated/0/in.mp4"
//        7 = "-i"
//        8 = "/storage/emulated/0/logo.png"
//        9 = "-filter_complex"
//        10 = "overlay"
//        11 = "-threads"
//        12 = "16"
//        13 = "-s"
//        14 = "640x360"
//        15 = "-c:v"
//        16 = "libx264"
//        17 = "-c:a"
//        18 = "aac"
//        19 = "-tune"
//        20 = "zerolatency"
//        21 = "-r"
//        22 = "30000/1001"
//        23 = "-y"
//        24 = "/storage/emulated/0/result1.mp4"
//        String[] complexCommand = {"ffmpeg",
//                "-i", path,
//                "-i", WATERMARK_PATH,
////                "-filter_complex","overlay=W-w",
//                "-filter_complex", "overlay=main_w-overlay_w-10:10",
//                "-threads", "16",
//                "-s", videoEntity.getWidth() + "x" + videoEntity.getHeight(),
//                "-c:v", "libx264",
//                "-c:a", "aac",
//                "-tune", "zerolatency",
//                "-f", "mp4",
//                "-r", videoEntity.getFramerate() + "",
//                "-g", "1",
//                "-b", videoEntity.getBitrate() + "",
//                "-y", videoOutputPath};
//        String[] complexCommand = {"ffmpeg",
//                "-i", path,
//                "-i", WATERMARK_PATH,
////                "-filter_complex","overlay=W-w",
//                "-filter_complex", "overlay=main_w-overlay_w-10:10",
//                "-threads", "16",
//                "-s", videoEntity.getWidth() + "x" + videoEntity.getHeight(),
//                "-c:v", "libx264",
//                "-c:a", "aac",
//                "-tune", "zerolatency",
//                "-f", "mp4",
//                "-r", videoEntity.getFramerate() + "",
//                "-b", videoEntity.getBitrate() + "",
//                "-y", videoOutputPath};

        String[] complexCommand = {"ffmpeg",
                "-i", path,
                "-ss", "00:00:00",
                "-t", "10",
                "-i", Environment.getExternalStorageDirectory() + File.separator+"test"+File.separator+"adiao.mp3",
                "-y", videoOutputPath,
        };
        return complexCommand;
    }

    private void prepare() {

        RxFileTool.createOrExistsDir(VIDEO_DIR);
        RxFileTool.createOrExistsDir(TRANSCODER_DIR);
        RxFileTool.createOrExistsFile(NO_MEDIA);
        // 检查水印文件夹是否存在，不存在则创建
        checkWaterMark();
        ffmpeg = FFmpegUtils.getInstance();
        // 这里是为了确保屏幕锁屏后 App依然能够确保后台继续运行转码工作。
        PowerManager powerManager = (PowerManager) getApp().getSystemService(Activity.POWER_SERVICE);
        wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "VK_LOCK");
        wakeLock.acquire();
    }

    private String getFileName(String path) {
        String fileName = RxFileTool.getFileName(path);
        if (!TextUtils.isEmpty(fileName) && fileName.contains(".")) {
            String name[] = fileName.split("\\.");
            if (name.length > 0) {
                fileName = name[0];
                fileName = fileName + ".mp4";
            }
        }
        return fileName;
    }

    public void start(final String path) {
        callback.finish(path);
//        if (!RxFileTool.fileExists(path)) {
//            ToastX.show("抱歉，视频文件不存在或被删除");
//            return;
//        }
//        videoInputPath = path;
//        new Thread(new Runnable() {
//            @Override
//            public void run() {
//                prepare();
//                try {
//                    // 测试水印
//                    String[] complexCommand = createCommand(path);
//                    if (complexCommand == null || complexCommand.length <= 0) {
//                        if (callback != null) {
//                            callback.failed("抱歉，指令生成失败");
//                        }
//                        return;
//                    }
//
//                    int code = ffmpeg.execffmpeg(complexCommand, ffmpegCallBack);
//                    Log.i("TranscoderUtils", "result code=" + code);
//
//                } catch (Exception e) {
//                    Log.e(TAG, "vk run exeption.", e);
//                    if (callback != null) {
//                        callback.failed("vk run exeption." + e);
//                    }
//                } finally {
//                    if (wakeLock.isHeld()) {
//                        wakeLock.release();
//                        Log.i(TAG, "Wake lock released");
//                    }
//                }
//            }
//        }).start();

    }

    // 检查水印文件夹是否存在，不存在则创建
    private void checkWaterMark() {
        RxFileTool.createOrExistsDir(WATERMARK_DIR);
        try {
            InputStream is = MyApp.getAppContext().getAssets().open("aiyige_logo.png");
            if (is != null) {
                RxFileTool.copyFile(is, new File(WATERMARK_PATH));
            }
        } catch (IOException e) {
            Timber.e("checkWaterMark:" + Log.getStackTraceString(e));
        }
    }

    private MyApp getApp() {
        return MyApp.getInstance();
    }

    public void exit() {
        if (ffmpeg != null) {
            ffmpeg.exitffmpeg();
        }
        if (wakeLock != null) {
            if (wakeLock.isHeld()) {
                wakeLock.release();
                Log.i(TAG, "Wake lock released");
            }
        }
        RxFileTool.delAllFile(VIDEO_DIR);
    }


    public class VideoEntity {

        public int getWidth() {
            return (width > 1280 || width == 0) ? 1280 : width;
        }

        public void setWidth(int width) {
            this.width = width;
        }

        public int getHeight() {
            return (height > 720 || height == 0) ? 720 : height;
        }

        public void setHeight(int height) {
            this.height = height;
        }

        public String getBitrate() {
            long btr = bitrate / 1000;
            if (btr <= 0) {
                btr = 1500;
            }
            return (btr > 1500 ? 1500 : btr) + "k";
        }

        public void setBitrate(long bitrate) {
            this.bitrate = bitrate;
        }

        public String getBitrateValue() {
            return bitrate / 1000 + "k";
        }

        public int getFramerate() {
            return framerate <= 25 ? 25 : framerate;
        }

        public void setFramerate(int framerate) {
            this.framerate = framerate;
        }

        public long getDuration() {
            return duration;
        }

        public void setDuration(long duration) {
            this.duration = duration;
            TranscoderUtils.this.mDuration = duration;

        }

        public String getTitle() {
            return title;
        }

        public void setTitle(String title) {
            this.title = title;
        }

        public long bitrate;

        public int framerate;

        public long duration;

        public String title;

        public int width;

        public int height;
    }

    public FFmpegCallBack ffmpegCallBack = new FFmpegCallBack() {
        @Override
        public void onStart() {
        }

        @Override
        public void onCallBackLog(String log) {
            Log.i(TAG, "onCallBackLog===" + log);
        }

        @Override
        public void onCallBackPrint(String msg) {
            Log.i(TAG, "onCallBackPrint===" + msg);
        }

        @Override
        public void onProgress(int frame_number, int milli_second) {
            Log.i(TAG, "onProgress===frame_number:" + frame_number + "   milli_second=" + milli_second);
            if (mDuration > 0 && milli_second > 0) {
                int progress = (int) ((double) milli_second / mDuration * 100d);
                if (callback != null) {
                    callback.progress(progress);
                }
            }
        }

        @Override
        public void onSuccess() {
            if (callback != null) {
                callback.progress(100);
                callback.finish(videoOutputPath);
            }
        }

        @Override
        public void onFailure(int result) {
            if (callback != null) {
                callback.failed("" + result);
            }

        }

    };


    public interface TranscoderCallback {

        void failed(String error);

        void cancel();

        void finish(String path);

        void progress(int progress);

        void start(String videoInfo);
    }


}
